package com.szh.zx.duoxiancheng.chapter1;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 演示tryLock（）
 */
public class Account {
    private Lock lock = new ReentrantLock();
    private volatile double money;

    public Account(double money) {
        this.money = money;
    }

    public double getMoney() {
        return money;
    }

    void lock() {
        lock.lock();
    }

    void unlock() {
        lock.unlock();
    }

    boolean tryLock() {
        return lock.tryLock();
    }

    public void reduce(double money) {
        lock.lock();
        try {
            this.money -= money;
        } finally {
            lock.unlock();
        }
    }

    public void add(double money) {
        lock.lock();
        try {
            this.money += money;
        } finally {
            lock.unlock();
        }
    }

    static class AccountMgr {
        // 不应该这样
/*        public static void transfer(Account from, Account to, double money) throws Exception {
            from.lock;
            try {
                to.lock;
                try {
                    if (from.getMoney() >= money) {
                        from.reduce(money);
                        to.add(money);
                    } else {
                        throw new Exception(from + "没有足够的钱");
                    }
                } finally {
                    to.unlock();
                }
            } finally {
                from.unlock();
            }
        }*/

        // 应该这样
        public static boolean tryTransfer(Account from, Account to, double money) throws Exception {
            if (from.tryLock()) {
                try {
                    if (to.tryLock()) {
                        try {
                            if (from.getMoney() >= money) {
                                from.reduce(money);
                                to.add(money);
                            } else {
                                throw new Exception(from + "没有足够的钱");
                            }
                            return true;
                        } finally {
                            to.unlock();
                        }

                    }
                } finally {
                    from.unlock();
                }
            }
            return false;
        }
    }

}
